home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-10-24 | 48.2 KB | 2,266 lines |
- Newsgroups: comp.sources.misc
- From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
- Subject: v24i008: zsh2.1 - The Z shell, Part08/19
- Message-ID: <1991Oct24.190925.25848@sparky.imd.sterling.com>
- X-Md4-Signature: 45b7c4db263877d30de733d36d186705
- Date: Thu, 24 Oct 1991 19:09:25 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
- Posting-number: Volume 24, Issue 8
- Archive-name: zsh2.1/part08
- Environment: BSD
- Supersedes: zsh2.00: Volume 18, Issue 84-98
-
- #!/bin/sh
- # this is zshar.08 (part 8 of zsh2.1.0)
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file zsh2.1/src/jobs.c continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 8; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test ! -f _shar_wnt_.tmp; then
- echo 'x - still skipping zsh2.1/src/jobs.c'
- else
- echo 'x - continuing file zsh2.1/src/jobs.c'
- sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.1/src/jobs.c' &&
- X
- X zsh is distributed in the hope that it will be useful, but
- X WITHOUT ANY WARRANTY. No author or distributor accepts
- X responsibility to anyone for the consequences of using it or for
- X whether it serves any particular purpose or works at all, unless he
- X says so in writing. Refer to the GNU General Public License
- X for full details.
- X
- X Everyone is granted permission to copy, modify and redistribute
- X zsh, but only under the conditions described in the GNU General Public
- X License. A copy of this license is supposed to have been given to you
- X along with zsh so you can know your rights and responsibilities.
- X It should be in a file named COPYING.
- X
- X Among other things, the copyright notice and this notice must be
- X preserved on all copies.
- X
- X*/
- X
- X#include "zsh.h"
- X#include <sys/errno.h>
- X
- X/* != 0 means the handler is active */
- X
- Xstatic int handling = 0;
- X
- X/* != 0 means the shell is waiting for a job to complete */
- X
- Xstatic int waiting = 0;
- X
- X#ifdef INTHANDTYPE
- X#define RETURN return 0
- X#else
- X#define RETURN return
- X#endif
- X
- X/* the signal handler */
- X
- XHANDTYPE handler(sig,code) /**/
- Xint sig;int code;
- X{
- Xlong pid;
- Xint statusp;
- XJob jn;
- Xstruct process *pn;
- Xstruct rusage ru;
- X
- X#ifdef RESETHANDNEEDED
- X signal(sig,handler);
- X#endif
- X if (sig == SIGINT)
- X {
- X if (sigtrapped[SIGINT])
- X dotrap(SIGINT);
- X else
- X errflag = 1;
- X RETURN;
- X }
- X#ifdef SIGWINCH
- X if (sig == SIGWINCH)
- X adjustwinsize();
- X#endif
- X if (sig != SIGCHLD)
- X {
- X dotrap(sig);
- X if (sig == SIGALRM && !sigtrapped[SIGALRM])
- X {
- X zerr("timeout",NULL,0);
- X exit(1);
- X }
- X RETURN;
- X }
- X for (;;)
- X {
- X#ifdef SYSV
- X pid = wait(&statusp);
- X#else
- X#if defined(RLIM_INFINITY) & ! defined(__hpux)
- X pid = wait3(&statusp,WNOHANG|WUNTRACED,&ru);
- X#else
- X pid = wait3(&statusp,WNOHANG|WUNTRACED,NULL);
- X#endif
- X#endif
- X if (pid == -1)
- X {
- X if (errno != ECHILD)
- X zerr("wait failed: %e",NULL,errno);
- X RETURN;
- X }
- X if (!pid)
- X RETURN;
- X findproc(pid,&jn,&pn); /* find the process of this pid */
- X if (jn)
- X {
- X pn->statusp = statusp;
- X handling = 1;
- X pn->ru = ru;
- X pn->endtime = time(NULL);
- X updatestatus(jn);
- X handling = 0;
- X if (zleactive)
- X refresh();
- X }
- X else if (WIFSTOPPED(SP(statusp)))
- X kill(pid,SIGKILL); /* kill stopped untraced children */
- X }
- X RETURN;
- X}
- X
- X/* change job table entry from stopped to running */
- X
- Xvoid makerunning(jn) /**/
- XJob jn;
- X{
- Xstruct process *pn;
- X
- X jn->stat &= ~STAT_STOPPED;
- X for (pn = jn->procs; pn; pn = pn->next)
- X if (WIFSTOPPED(SP(pn->statusp)))
- X pn->statusp = SP_RUNNING;
- X}
- X
- X/* update status of job, possibly printing it */
- X
- Xvoid updatestatus(jn) /**/
- XJob jn;
- X{
- Xstruct process *pn;
- Xint notrunning = 1,alldone = 1,val,job = jn-jobtab,somestopped = 0;
- X
- X for (pn = jn->procs; pn; pn = pn->next)
- X {
- X if (pn->statusp == SP_RUNNING)
- X notrunning = 0;
- X if (pn->statusp == SP_RUNNING || WIFSTOPPED(SP(pn->statusp)))
- X alldone = 0;
- X if (WIFSTOPPED(SP(pn->statusp)))
- X somestopped = 1;
- X if (!pn->next && jn)
- X val = (WIFSIGNALED(SP(pn->statusp))) ?
- X 0200 | WTERMSIG(SP(pn->statusp)) : WEXITSTATUS(SP(pn->statusp));
- X }
- X if (!notrunning)
- X return;
- X if (somestopped && (jn->stat & STAT_STOPPED))
- X return;
- X jn->stat |= (alldone) ? STAT_CHANGED|STAT_DONE :
- X STAT_CHANGED|STAT_STOPPED;
- X if (alldone && job == thisjob)
- X {
- X if (!val) {
- X gettyinfo(&shttyinfo);
- X if (interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))
- X sanetty(&shttyinfo);
- X#ifdef TIOCSWINSZ
- X if (!(columns = shttyinfo.winsize.ws_col))
- X columns = 80;
- X lines = shttyinfo.winsize.ws_row;
- X#endif
- X } else
- X settyinfo(&shttyinfo);
- X lastval = val;
- X }
- X if ((jn->stat & (STAT_DONE|STAT_STOPPED)) == STAT_STOPPED) {
- X prevjob = curjob;
- X curjob = job;
- X }
- X if ((isset(NOTIFY) || job == thisjob) && jn->stat & STAT_LOCKED)
- X printjob(jn,!!isset(LONGLISTJOBS));
- X if (sigtrapped[SIGCHLD] && job != thisjob)
- X dotrap(SIGCHLD);
- X}
- X
- X/* find process and job associated with pid */
- X
- Xvoid findproc(pid,jptr,pptr) /**/
- Xint pid;Job *jptr;struct process **pptr;
- X{
- Xstruct process *pn;
- Xint jn;
- X
- X for (jn = 1; jn != MAXJOB; jn++)
- X for (pn = jobtab[jn].procs; pn; pn = pn->next)
- X if (pn->pid == pid)
- X {
- X *pptr = pn;
- X *jptr = jobtab+jn;
- X return;
- X }
- X *pptr = NULL;
- X *jptr = NULL;
- X}
- X
- X/*
- X lng = 0 means jobs
- X lng = 1 means jobs -l
- X lng = 2 means jobs -p
- X*/
- X
- Xvoid printjob(jn,lng) /**/
- XJob jn;int lng;
- X{
- Xint job = jn-jobtab,len = 9,sig = -1,sflag = 0,llen,printed = 0;
- Xint conted = 0,lineleng = getlineleng(),skip = 0,doputnl = 0;
- Xstruct process *pn;
- X
- X if (lng < 0)
- X {
- X conted = 1;
- X lng = 0;
- X }
- X
- X /* find length of longest signame, check to see if we
- X really need to print this job */
- X
- X for (pn = jn->procs; pn; pn = pn->next)
- X {
- X if (pn->statusp != SP_RUNNING)
- X if (WIFSIGNALED(SP(pn->statusp)))
- X {
- X sig = WTERMSIG(SP(pn->statusp));
- X llen = strlen(sigmsg[sig]);
- X if (WCOREDUMPED(pn->statusp))
- X llen += 14;
- X if (llen > len)
- X len = llen;
- X if (sig != SIGINT && sig != SIGPIPE)
- X sflag = 1;
- X else if (sig == SIGINT)
- X errflag = 1;
- X if (job == thisjob && sig == SIGINT)
- X doputnl = 1;
- X }
- X else if (WIFSTOPPED(SP(pn->statusp)))
- X {
- X sig = WSTOPSIG(SP(pn->statusp));
- X if (strlen(sigmsg[sig]) > len)
- X len = strlen(sigmsg[sig]);
- X if (job == thisjob && sig == SIGTSTP)
- X doputnl = 1;
- X }
- X else if (isset(PRINTEXITVALUE) && WEXITSTATUS(SP(pn->statusp)))
- X sflag = 1;
- X }
- X
- X /* print if necessary */
- X
- X if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag ||
- X job != thisjob))
- X {
- X int len2,fline = 1;
- X struct process *qn;
- X
- X trashzle();
- X if (doputnl)
- X putc('\n',stderr);
- X for (pn = jn->procs; pn;)
- X {
- X len2 = ((job == thisjob) ? 5 : 10)+len; /* 2 spaces */
- X if (lng)
- X qn = pn->next;
- X else for (qn = pn->next; qn; qn = qn->next)
- X {
- X if (qn->statusp != pn->statusp)
- X break;
- X if (strlen(qn->text)+len2+((qn->next) ? 3 : 0) > lineleng)
- X break;
- X len2 += strlen(qn->text)+2;
- X }
- X if (job != thisjob)
- X if (fline)
- X fprintf(stderr,"[%d] %c ",jn-jobtab,(job == curjob) ? '+' :
- X (job == prevjob) ? '-' : ' ');
- X else
- X fprintf(stderr,(job > 9) ? " " : " ");
- X else
- X fprintf(stderr,"zsh: ");
- X if (lng)
- X if (lng == 1)
- X fprintf(stderr,"%d ",pn->pid);
- X else
- X {
- X int x = jn->gleader;
- X
- X fprintf(stderr,"%d ",x);
- X do skip++; while (x /= 10);
- X skip++;
- X lng = 0;
- X }
- X else
- X fprintf(stderr,"%*s",skip,"");
- X if (pn->statusp == SP_RUNNING)
- X if (!conted)
- X fprintf(stderr,"running%*s",len-7+2,"");
- X else
- X fprintf(stderr,"continued%*s",len-9+2,"");
- X else if (WIFEXITED(SP(pn->statusp)))
- X if (WEXITSTATUS(SP(pn->statusp)))
- X fprintf(stderr,"exit %-4d%*s",WEXITSTATUS(SP(pn->statusp)),
- X len-9+2,"");
- X else
- X fprintf(stderr,"done%*s",len-4+2,"");
- X else if (WIFSTOPPED(SP(pn->statusp)))
- X fprintf(stderr,"%-*s",len+2,sigmsg[WSTOPSIG(SP(pn->statusp))]);
- X else if (WCOREDUMPED(pn->statusp))
- X fprintf(stderr,"%s (core dumped)%*s",
- X sigmsg[WTERMSIG(SP(pn->statusp))],
- X len-14+2-strlen(sigmsg[WTERMSIG(SP(pn->statusp))]),"");
- X else
- X fprintf(stderr,"%-*s",len+2,sigmsg[WTERMSIG(SP(pn->statusp))]);
- X for (; pn != qn; pn = pn->next)
- X fprintf(stderr,(pn->next) ? "%s | " : "%s",pn->text);
- X putc('\n',stderr);
- X fline = 0;
- X }
- X printed = 1;
- X }
- X else if (doputnl && interact)
- X putc('\n',stderr);
- X fflush(stderr);
- X
- X /* print "(pwd now: foo)" messages */
- X
- X if (interact && job==thisjob && strcmp(jn->cwd,cwd))
- X {
- X printf("(pwd now: ");
- X printdir(cwd);
- X printf(")\n");
- X fflush(stdout);
- X }
- X
- X /* delete job if done */
- X
- X if (jn->stat & STAT_DONE)
- X {
- X static struct job zero;
- X struct process *nx;
- X char *s;
- X
- X if (jn->stat & STAT_TIMED)
- X {
- X dumptime(jn);
- X printed = 1;
- X }
- X for (pn = jn->procs; pn; pn = nx)
- X {
- X nx = pn->next;
- X if (pn->text)
- X free(pn->text);
- X free(pn);
- X }
- X free(jn->cwd);
- X if (jn->filelist)
- X {
- X while (s = getnode(jn->filelist))
- X {
- X unlink(s);
- X free(s);
- X }
- X free(jn->filelist);
- X }
- X *jn = zero;
- X if (job == curjob)
- X {
- X curjob = prevjob;
- X prevjob = job;
- X }
- X if (job == prevjob)
- X setprevjob();
- X }
- X else
- X jn->stat &= ~STAT_CHANGED;
- X}
- X
- X/* set the previous job to something reasonable */
- X
- Xvoid setprevjob() /**/
- X{
- Xint t0;
- X
- X for (t0 = MAXJOB-1; t0; t0--)
- X if ((jobtab[t0].stat & STAT_INUSE) && (jobtab[t0].stat & STAT_STOPPED) &&
- X t0 != curjob && t0 != thisjob)
- X break;
- X if (!t0)
- X for (t0 = MAXJOB-1; t0; t0--)
- X if ((jobtab[t0].stat & STAT_INUSE) && t0 != curjob && t0 != thisjob)
- X break;
- X prevjob = (t0) ? t0 : -1;
- X}
- X
- X/* initialize a job table entry */
- X
- Xvoid initjob() /**/
- X{
- X jobtab[thisjob].cwd = ztrdup(cwd);
- X jobtab[thisjob].stat = STAT_INUSE;
- X jobtab[thisjob].gleader = 0;
- X}
- X
- X/* add a process to the current job */
- X
- Xstruct process *addproc(pid,text) /**/
- Xlong pid;char *text;
- X{
- Xstruct process *process;
- X
- X if (!jobtab[thisjob].gleader)
- X jobtab[thisjob].gleader = lastpid = pid;
- X lastpid = pid;
- X process = zcalloc(sizeof *process);
- X process->pid = pid;
- X process->text = text;
- X process->next = NULL;
- X process->statusp = SP_RUNNING;
- X process->bgtime = time(NULL);
- X if (jobtab[thisjob].procs)
- X {
- X struct process *n;
- X
- X for (n = jobtab[thisjob].procs; n->next && !n->next->lastfg; n = n->next);
- X process->next = n->next;
- X n->next = process;
- X }
- X else
- X jobtab[thisjob].procs = process;
- X return process;
- X}
- X
- X/* determine if it's all right to exec a command without
- X forking in last component of subshells; it's not ok if we have files
- X to delete */
- X
- Xint execok() /**/
- X{
- XJob jn;
- X
- X if (!exiting)
- X return 0;
- X for (jn = jobtab+1; jn != jobtab+MAXJOB; jn++)
- X if (jn->stat && jn->filelist)
- X return 0;
- X return 1;
- X}
- X
- X/* wait for a job to finish */
- X
- Xvoid waitjob(job) /**/
- Xint job;
- X{
- Xstatic struct job zero;
- XJob jn;
- X
- X if (jobtab[job].procs) /* if any forks were done */
- X {
- X jobtab[job].stat |= STAT_LOCKED;
- X waiting = 1;
- X if (jobtab[job].stat & STAT_CHANGED)
- X printjob(jobtab+job,!!isset(LONGLISTJOBS));
- X while (jobtab[job].stat &&
- X !(jobtab[job].stat & (STAT_DONE|STAT_STOPPED)))
- X chldsuspend();
- X waiting = 0;
- X }
- X else /* else do what printjob() usually does */
- X {
- X char *s;
- X
- X jn = jobtab+job;
- X free(jn->cwd);
- X if (jn->filelist)
- X {
- X while (s = getnode(jn->filelist))
- X {
- X unlink(s);
- X free(s);
- X }
- X free(jn->filelist);
- X }
- X *jn = zero;
- X }
- X}
- X
- X/* wait for running job to finish */
- X
- Xvoid waitjobs() /**/
- X{
- X waitjob(thisjob);
- X thisjob = -1;
- X}
- X
- X/* clear job table when entering subshells */
- X
- Xvoid clearjobtab() /**/
- X{
- Xstatic struct job zero;
- Xint t0;
- X
- X for (t0 = 1; t0 != MAXJOB; t0++)
- X jobtab[thisjob] = zero;
- X}
- X
- X/* get a free entry in the job table to use */
- X
- Xint getfreejob() /**/
- X{
- Xint t0;
- X
- X for (t0 = 1; t0 != MAXJOB; t0++)
- X if (!jobtab[t0].stat) {
- X jobtab[t0].stat |= STAT_INUSE;
- X return t0;
- X }
- X zerr("job table full or recursion limit exceeded",NULL,0);
- X return -1;
- X}
- X
- X/* print pids for & */
- X
- Xvoid spawnjob() /**/
- X{
- Xstruct process *pn;
- X
- X if (!subsh)
- X {
- X if (curjob == -1 || !(jobtab[curjob].stat & STAT_STOPPED))
- X {
- X curjob = thisjob;
- X setprevjob();
- X }
- X else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED))
- X prevjob = thisjob;
- X if (interact && jobbing && jobtab[thisjob].procs)
- X {
- X fprintf(stderr,"[%d]",thisjob);
- X for (pn = jobtab[thisjob].procs; pn; pn = pn->next)
- X fprintf(stderr," %d",pn->pid);
- X fprintf(stderr,"\n");
- X fflush(stderr);
- X }
- X }
- X if (!jobtab[thisjob].procs)
- X {
- X char *s;
- X static struct job zero;
- X struct job *jn;
- X
- X jn = jobtab+thisjob;
- X free(jn->cwd);
- X if (jn->filelist)
- X {
- X while (s = getnode(jn->filelist))
- X {
- X unlink(s);
- X free(s);
- X }
- X free(jn->filelist);
- X }
- X *jn = zero;
- X }
- X else
- X jobtab[thisjob].stat |= STAT_LOCKED;
- X thisjob = -1;
- X}
- X
- Xvoid fixsigs() /**/
- X{
- X unblockchld();
- X}
- X
- Xvoid printtime(real,ru,desc) /**/
- Xtime_t real;struct rusage *ru;char *desc;
- X{
- Xchar *s;
- X
- X if (!desc)
- X desc = "";
- X for (s = (timefmt) ? timefmt : DEFTIMEFMT; *s; s++)
- X if (*s == '%')
- X switch(s++,*s)
- X {
- X case 'E': fprintf(stderr,"%lds",real); break;
- X case 'U': fprintf(stderr,"%ld.%03lds",
- X ru->ru_utime.tv_sec,ru->ru_utime.tv_usec/1000); break;
- X case 'S': fprintf(stderr,"%ld.%03lds",
- X ru->ru_stime.tv_sec,ru->ru_stime.tv_usec/1000); break;
- X case 'P':
- X if (real)
- X fprintf(stderr,"%d%%",
- X (int) (100*ru->ru_utime.tv_sec+ru->ru_stime.tv_sec)
- X / real);
- X break;
- X case 'W': fprintf(stderr,"%ld",ru->ru_nswap); break;
- X case 'X': fprintf(stderr,"%ld",ru->ru_ixrss); break;
- X case 'D': fprintf(stderr,"%ld",ru->ru_idrss); break;
- X case 'K': fprintf(stderr,"%ld",ru->ru_ixrss+ru->ru_idrss); break;
- X case 'M': fprintf(stderr,"%ld",ru->ru_maxrss); break;
- X case 'F': fprintf(stderr,"%ld",ru->ru_majflt); break;
- X case 'R': fprintf(stderr,"%ld",ru->ru_minflt); break;
- X case 'I': fprintf(stderr,"%ld",ru->ru_inblock); break;
- X case 'O': fprintf(stderr,"%ld",ru->ru_oublock); break;
- X case 'r': fprintf(stderr,"%ld",ru->ru_msgrcv); break;
- X case 's': fprintf(stderr,"%ld",ru->ru_msgsnd); break;
- X case 'k': fprintf(stderr,"%ld",ru->ru_nsignals); break;
- X case 'w': fprintf(stderr,"%ld",ru->ru_nvcsw); break;
- X case 'c': fprintf(stderr,"%ld",ru->ru_nivcsw); break;
- X default: fprintf(stderr,"%%%c",s[-1]); break;
- X }
- X else
- X putc(*s,stderr);
- X putc('\n',stderr);
- X fflush(stderr);
- X}
- X
- Xvoid dumptime(jn) /**/
- XJob jn;
- X{
- Xstruct process *pn = jn->procs;
- X
- X if (!jn->procs)
- X return;
- X for (pn = jn->procs; pn; pn = pn->next)
- X printtime(pn->endtime-pn->bgtime,&pn->ru,pn->text);
- X}
- X
- X/* SIGHUP any jobs left running */
- X
- Xvoid killrunjobs() /**/
- X{
- Xint t0,killed = 0;
- X
- X if (isset(NOHUP)) return;
- X for (t0 = 1; t0 != MAXJOB; t0++)
- X if (t0 != thisjob && jobtab[t0].stat &&
- X !(jobtab[t0].stat & STAT_STOPPED))
- X {
- X kill(-jobtab[t0].gleader,SIGHUP);
- X killed++;
- X }
- X if (killed)
- X zerr("warning: %d jobs SIGHUPed",NULL,killed);
- X}
- X
- X/* check to see if user has jobs running/stopped */
- X
- Xvoid checkjobs() /**/
- X{
- Xint t0;
- X
- X for (t0 = 1; t0 != MAXJOB; t0++)
- X if (t0 != thisjob && jobtab[t0].stat)
- X break;
- X if (t0 != MAXJOB)
- X {
- X if (jobtab[t0].stat & STAT_STOPPED)
- X {
- X#ifdef USE_SUSPENDED
- X zerr("you have suspended jobs.",NULL,0);
- X#else
- X zerr("you have stopped jobs.",NULL,0);
- X#endif
- X }
- X else
- X zerr("you have running jobs.",NULL,0);
- X stopmsg = 1;
- X }
- X}
- X
- X/* send a signal to a job (simply involves kill if monitoring is on) */
- X
- Xint killjb(jn,sig) /**/
- XJob jn;int sig;
- X{
- Xstruct process *pn;
- Xint err;
- X
- X if (jobbing)
- X return(kill(-jn->gleader,sig));
- X for (pn = jn->procs; pn; pn = pn->next)
- X if ((err = kill(pn->pid,sig)) == -1 && errno != ESRCH)
- X return -1;
- X return err;
- X}
- X
- SHAR_EOF
- echo 'File zsh2.1/src/jobs.c is complete' &&
- chmod 0644 zsh2.1/src/jobs.c ||
- echo 'restore of zsh2.1/src/jobs.c failed'
- Wc_c="`wc -c < 'zsh2.1/src/jobs.c'`"
- test 14918 -eq "$Wc_c" ||
- echo 'zsh2.1/src/jobs.c: original size 14918, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= zsh2.1/src/lex.c ==============
- if test -f 'zsh2.1/src/lex.c' -a X"$1" != X"-c"; then
- echo 'x - skipping zsh2.1/src/lex.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting zsh2.1/src/lex.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/lex.c' &&
- X/*
- X
- X lex.c - lexical analysis
- X
- X This file is part of zsh, the Z shell.
- X
- X zsh is free software; no one can prevent you from reading the source
- X code, or giving it to someone else.
- X This file is copyrighted under the GNU General Public License, which
- X can be found in the file called COPYING.
- X
- X Copyright (C) 1990, 1991 Paul Falstad
- X
- X zsh is distributed in the hope that it will be useful, but
- X WITHOUT ANY WARRANTY. No author or distributor accepts
- X responsibility to anyone for the consequences of using it or for
- X whether it serves any particular purpose or works at all, unless he
- X says so in writing. Refer to the GNU General Public License
- X for full details.
- X
- X Everyone is granted permission to copy, modify and redistribute
- X zsh, but only under the conditions described in the GNU General Public
- X License. A copy of this license is supposed to have been given to you
- X along with zsh so you can know your rights and responsibilities.
- X It should be in a file named COPYING.
- X
- X Among other things, the copyright notice and this notice must be
- X preserved on all copies.
- X
- X*/
- X
- X#include "zsh.h"
- X
- X/* lexical state */
- X
- Xstatic int xincmdpos,xincond,xincasepat,dbparens,xdbparens,xalstat;
- Xstatic char *xhlastw;
- X
- Xstatic int xisfirstln, xisfirstch, xhistremmed, xhistdone,
- X xspaceflag, xstophist, xlithist, xalstackind,xhlinesz;
- Xstatic char *xhline, *xhptr;
- X
- X/* save the lexical state */
- X
- X/* is this a hack or what? */
- X
- Xvoid lexsave() /**/
- X{
- X xincmdpos = incmdpos;
- X xincond = incond;
- X xincasepat = incasepat;
- X xdbparens = dbparens;
- X xalstat = alstat;
- X xalstackind = alstackind;
- X xisfirstln = isfirstln;
- X xisfirstch = isfirstch;
- X xhistremmed = histremmed;
- X xhistdone = histdone;
- X xspaceflag = spaceflag;
- X xstophist = stophist;
- X xlithist = lithist;
- X xhline = hline;
- X xhptr = hptr;
- X xhlastw = hlastw;
- X xhlinesz = hlinesz;
- X}
- X
- X/* restore lexical state */
- X
- Xvoid lexrestore() /**/
- X{
- X incmdpos = xincmdpos;
- X incond = xincond;
- X incasepat = xincasepat;
- X dbparens = xdbparens;
- X alstat = xalstat;
- X isfirstln = xisfirstln;
- X isfirstch = xisfirstch;
- X histremmed = xhistremmed;
- X histdone = xhistdone;
- X spaceflag = xspaceflag;
- X stophist = xstophist;
- X lithist = xlithist;
- X hline = xhline;
- X hptr = xhptr;
- X hlastw = xhlastw;
- X clearalstack();
- X alstackind = xalstackind;
- X hlinesz = xhlinesz;
- X lexstop = errflag = 0;
- X}
- X
- Xvoid yylex() /**/
- X{
- X if (tok == LEXERR) return;
- X do
- X tok = gettok();
- X while (tok != ENDINPUT && exalias());
- X isnewlin = (tok == NEWLIN && !inbufct);
- X if (tok == SEMI || tok == NEWLIN)
- X tok = SEPER;
- X}
- X
- Xvoid ctxtlex() /**/
- X{
- Xstatic int oldpos,inredir = 0;
- X
- X yylex();
- X switch (tok) {
- X case SEPER: case NEWLIN: case SEMI: case DSEMI: case AMPER:
- X case INPAR: case INBRACE: case DBAR: case DAMPER: case BAR:
- X case BARAMP: case INOUTPAR: case DO: case THEN: case ELIF:
- X case ELSE: incmdpos = 1; break;
- X case STRING: case ENVSTRING: case ENVARRAY: case OUTPAR:
- X case FOR: case SELECT: case FOREACH: case CASE: incmdpos = 0; break;
- X }
- X if (IS_REDIROP(tok)) {
- X inredir = 2;
- X oldpos = incmdpos;
- X incmdpos = 0;
- X } else if (inredir) {
- X if (!--inredir) incmdpos = oldpos;
- X else incmdpos = 0;
- X }
- X}
- X
- X#define LX1_BKSLASH 0
- X#define LX1_COMMENT 1
- X#define LX1_NEWLIN 2
- X#define LX1_SEMI 3
- X#define LX1_BANG 4
- X#define LX1_AMPER 5
- X#define LX1_BAR 6
- X#define LX1_INPAR 7
- X#define LX1_OUTPAR 8
- X#define LX1_INBRACE 9
- X#define LX1_OUTBRACE 10
- X#define LX1_INBRACK 11
- X#define LX1_OUTBRACK 12
- X#define LX1_INANG 13
- X#define LX1_OUTANG 14
- X#define LX1_OTHER 15
- X
- X#define LX2_BREAK 0
- X#define LX2_OUTPAR 1
- X#define LX2_BAR 2
- X#define LX2_STRING 3
- X#define LX2_INBRACK 4
- X#define LX2_OUTBRACK 5
- X#define LX2_TILDE 6
- X#define LX2_INPAR 7
- X#define LX2_INBRACE 8
- X#define LX2_OUTBRACE 9
- X#define LX2_OUTANG 10
- X#define LX2_INANG 11
- X#define LX2_EQUALS 12
- X#define LX2_BKSLASH 13
- X#define LX2_QUOTE 14
- X#define LX2_DQUOTE 15
- X#define LX2_BQUOTE 16
- X#define LX2_OTHER 17
- X
- Xunsigned char lexact1[256],lexact2[256],lextok2[256];
- X
- Xvoid initlextabs() /**/
- X{
- Xint t0;
- Xstatic char *lx1 = "\\q\n;!&|(){}[]<>xx";
- Xstatic char *lx2 = "x)|$[]~({}><=\\\'\"`x";
- X
- X for (t0 = 0; t0 != 256; t0++) {
- X lexact1[t0] = LX1_OTHER;
- X lexact2[t0] = LX2_OTHER;
- X lextok2[t0] = t0;
- X }
- X for (t0 = 0; lx1[t0]; t0++)
- X if (lx1[t0] != 'x')
- X lexact1[lx1[t0]] = t0;
- X for (t0 = 0; lx2[t0]; t0++)
- X if (lx2[t0] != 'x')
- X lexact2[lx2[t0]] = t0;
- X lexact2[';'] = LX2_BREAK;
- X lexact2['&'] = LX2_BREAK;
- X lextok2[','] = Comma;
- X lextok2['*'] = Star;
- X lextok2['?'] = Quest;
- X lextok2['{'] = Inbrace;
- X lextok2['['] = Inbrack;
- X lextok2['$'] = String;
- X}
- X
- X/* initialize lexical state */
- X
- Xvoid lexinit() /**/
- X{
- X incond = incasepat = nocorrect =
- X dbparens = alstat = lexstop = 0;
- X incmdpos = 1;
- X tok = ENDINPUT;
- X if (isset(EXTENDEDGLOB))
- X {
- X lextok2['#'] = Pound;
- X lextok2['^'] = Hat;
- X }
- X else
- X {
- X lextok2['#'] = '#';
- X lextok2['^'] = '^';
- X }
- X}
- X
- Xint len = 0,bsiz = 256;
- Xchar *bptr;
- X
- X/* add a char to the string buffer */
- X
- Xvoid add(c) /**/
- Xint c;
- X{
- X *bptr++ = c;
- X if (bsiz == ++len)
- X {
- X int newbsiz;
- X
- X newbsiz = bsiz * 8;
- X while (newbsiz < inbufct)
- X newbsiz *= 2;
- X bptr = len+(tokstr = hrealloc(tokstr,bsiz,newbsiz));
- X bsiz = newbsiz;
- X }
- X}
- X
- Xstatic void unadd()
- X{
- X bptr--; bsiz--;
- X}
- X
- Xint gettok() /**/
- X{
- Xint bct = 0,pct = 0,brct = 0;
- Xint c,d,intpos = 1;
- Xint peekfd = -1,peek;
- X
- Xbeginning:
- X hlastw = NULL;
- X tokstr = NULL;
- X parbegin = -1;
- X while (iblank(c = hgetc()) && !lexstop);
- X isfirstln = 0;
- X wordbeg = inbufct;
- X hwbegin();
- X hwaddc(c);
- X if (dbparens) /* handle ((...)) */
- X {
- X pct = 2;
- X peek = STRING;
- X len = dbparens = 0;
- X bptr = tokstr = ncalloc(bsiz = 256);
- X for (;;)
- X {
- X if (c == '(')
- X pct++;
- X else if (c == ')')
- X pct--;
- X else if (c == '\n')
- X {
- X zerr("parse error: )) expected",NULL,0);
- X peek = LEXERR;
- X return peek;
- X }
- X else if (c == '$')
- X c = Qstring;
- X if (pct >= 2)
- X add(c);
- X if (pct)
- X c = hgetc();
- X else
- X break;
- X }
- X *bptr = '\0';
- X return peek;
- X }
- X if (idigit(c)) /* handle 1< foo */
- X {
- X d = hgetc();
- X hungetc(d);
- X lexstop = 0;
- X if (d == '>' || d == '<')
- X {
- X peekfd = c-'0';
- X c = hgetc();
- X }
- X }
- X
- X /* chars in initial position in word */
- X
- X if (c == hashchar &&
- X (isset(INTERACTIVECOMMENTS) ||
- X (!zleparse && (!interact || unset(SHINSTDIN) || strin))))
- X {
- X /* changed hgetch to hgetc so comments appear in history */
- X stophist = 1;
- X while ((c = hgetc()) != '\n' && !lexstop);
- X if (c == '\n') {
- X hwaddc('\n');
- X peek = NEWLIN;
- X } else {
- X peek = (errflag) ? LEXERR : ENDINPUT;
- X errflag = 1;
- X }
- X return peek;
- X }
- X if (lexstop)
- X return (errflag) ? LEXERR : ENDINPUT;
- X switch (lexact1[(unsigned char) c])
- X {
- X case LX1_BKSLASH:
- X d = hgetc();
- X if (d == '\n')
- X goto beginning;
- X hungetc(d);
- X break;
- X case LX1_NEWLIN: return NEWLIN;
- X case LX1_SEMI:
- X d = hgetc();
- X if (d != ';')
- X {
- X hungetc(d);
- X return SEMI;
- X }
- X return DSEMI;
- X case LX1_BANG:
- X d = hgetc();
- X hungetc(d);
- X if (!inblank(d))
- X break;
- X if (incmdpos || incond)
- X return BANG;
- X break;
- X case LX1_AMPER:
- X d = hgetc();
- X if (d != '&')
- X {
- X hungetc(d);
- X return AMPER;
- X }
- X return DAMPER;
- X case LX1_BAR:
- X d = hgetc();
- X if (d == '|')
- X return DBAR;
- X else if (d == '&')
- X return BARAMP;
- X hungetc(d);
- X return BAR;
- X case LX1_INPAR:
- X d = hgetc();
- X if (d == '(' && incmdpos)
- X {
- X tokstr = strdup("let");
- X dbparens = 1;
- X return STRING;
- X }
- X else if (d == ')')
- X return INOUTPAR;
- X hungetc(d);
- X if (!(incond || incmdpos))
- X break;
- X return INPAR;
- X case LX1_OUTPAR: return OUTPAR;
- X case LX1_INBRACE: if (!incmdpos) break; return INBRACE;
- X case LX1_OUTBRACE: return OUTBRACE;
- X case LX1_INBRACK:
- X if (!incmdpos)
- X break;
- X d = hgetc();
- X if (d == '[')
- X return DINBRACK;
- X hungetc(d);
- X break;
- X case LX1_OUTBRACK:
- X if (!incond)
- X break;
- X d = hgetc();
- X if (d == ']')
- X return DOUTBRACK;
- X hungetc(d);
- X break;
- X case LX1_INANG:
- X d = hgetc();
- X if ((!incmdpos && d == '(') || incasepat) {
- X hungetc(d);
- X break;
- X } else if (d == '<') {
- X int e = hgetc();
- X
- X if (e == '(') {
- X hungetc(e);
- X hungetc(d);
- X peek = INANG;
- X } else if (e == '<')
- X peek = TRINANG;
- X else if (e == '-')
- X peek = DINANGDASH;
- X else {
- X hungetc(e);
- X peek = DINANG;
- X }
- X } else if (d == '&')
- X peek = INANGAMP;
- X else {
- X peek = INANG;
- X hungetc(d);
- X }
- X tokfd = peekfd;
- X return peek;
- X case LX1_OUTANG:
- X d = hgetc();
- X if (d == '(')
- X {
- X hungetc(d);
- X break;
- X }
- X else if (d == '&')
- X {
- X d = hgetc();
- X if (d == '!')
- X peek = OUTANGAMPBANG;
- X else
- X {
- X hungetc(d);
- X peek = OUTANGAMP;
- X }
- X }
- X else if (d == '!')
- X peek = OUTANGBANG;
- X else if (d == '>')
- X {
- X d = hgetc();
- X if (d == '&')
- X {
- X d = hgetc();
- X if (d == '!')
- X peek = DOUTANGAMPBANG;
- X else
- X {
- X hungetc(d);
- X peek = DOUTANGAMP;
- X }
- X }
- X else if (d == '!')
- X peek = DOUTANGBANG;
- X else if (d == '(')
- X {
- X hungetc(d);
- X hungetc('>');
- X peek = OUTANG;
- X }
- X else
- X {
- X hungetc(d);
- X peek = DOUTANG;
- X if (isset(NOCLOBBER)) hwaddc('!');
- X }
- X }
- X else
- X {
- X hungetc(d);
- X peek = OUTANG;
- X if (isset(NOCLOBBER)) hwaddc('!');
- X }
- X tokfd = peekfd;
- X return peek;
- X }
- X
- X /* we've started a string, now get the rest of it, performing
- X tokenization */
- X
- X peek = STRING;
- X len = 0;
- X bptr = tokstr = ncalloc(bsiz = 256);
- X for(;;)
- X {
- X int act;
- X int d;
- X
- X if (inblank(c))
- X act = LX2_BREAK;
- X else
- X {
- X act = lexact2[(unsigned char) c];
- X c = lextok2[(unsigned char) c];
- X }
- X switch (act)
- X {
- X case LX2_BREAK: goto brk;
- X case LX2_OUTPAR:
- X if (!pct)
- X goto brk;
- X c = Outpar;
- X pct--;
- X break;
- X case LX2_BAR:
- X if (!pct && !incasepat)
- X goto brk;
- X c = Bar;
- X break;
- X case LX2_STRING:
- X d = hgetc();
- X if (d == '[')
- X {
- X add(String);
- X add(Inbrack);
- X while ((c = hgetc()) != ']' && !lexstop)
- X add(c);
- X c = Outbrack;
- X }
- X else if (d == '(')
- X {
- X add(String);
- X if (skipcomm()) { peek = LEXERR; goto brk; }
- X c = Outpar;
- X }
- X else
- X hungetc(d);
- X break;
- X case LX2_INBRACK: brct++; break;
- X case LX2_OUTBRACK:
- X if (incond && !brct)
- X goto brk;
- X brct--;
- X c = Outbrack;
- X break;
- X case LX2_TILDE: /* if (intpos) */ c = Tilde; break;
- X case LX2_INPAR:
- X d = hgetc();
- X hungetc(d);
- X if (d == ')' || incmdpos)
- X goto brk;
- X pct++;
- X c = Inpar;
- X break;
- X case LX2_INBRACE: bct++; break;
- X case LX2_OUTBRACE:
- X if (!bct)
- X goto brk;
- X bct--;
- X c = Outbrace;
- X break;
- X case LX2_OUTANG:
- X d = hgetc();
- X if (d != '(')
- X {
- X hungetc(d);
- X goto brk;
- X }
- X add(Outang);
- X if (skipcomm()) { peek = LEXERR; goto brk; }
- X c = Outpar;
- X break;
- X case LX2_INANG:
- X d = hgetc();
- X if (!(idigit(d) || d == '-' || d == '>' || d == '(' || d == ')'))
- X {
- X hungetc(d);
- X goto brk;
- X }
- X c = Inang;
- X if (d == '(')
- X {
- X add(c);
- X if (skipcomm()) { peek = LEXERR; goto brk; }
- X c = Outpar;
- X }
- X else if (d == ')')
- X hungetc(d);
- X else
- X {
- X add(c);
- X c = d;
- X while (c != '>' && !lexstop)
- X add(c),c = hgetc();
- X c = Outang;
- X }
- X break;
- X case LX2_EQUALS:
- X if (intpos)
- X {
- X d = hgetc();
- X if (d != '(')
- X {
- X hungetc(d);
- X c = Equals;
- X }
- X else
- X {
- X add(Equals);
- X if (skipcomm()) { peek = LEXERR; goto brk; }
- X c = Outpar;
- X }
- X }
- X else if (peek != ENVSTRING && incmdpos)
- X {
- X d = hgetc();
- X if (d == '(' && incmdpos)
- X {
- X *bptr = '\0';
- X return ENVARRAY;
- X }
- X hungetc(d);
- X peek = ENVSTRING;
- X intpos = 2;
- X }
- X break;
- X case LX2_BKSLASH:
- X c = hgetc();
- X if (c == '\n')
- X {
- X c = hgetc();
- X continue;
- X }
- X add(c);
- X c = hgetc();
- X continue;
- X case LX2_QUOTE:
- X add(Nularg);
- X
- X /* we add the Nularg to prevent this:
- X
- X echo $PA'TH'
- X
- X from printing the path. */
- X
- X for (;;) {
- X while ((c = hgetc()) != '\'' && !lexstop) {
- X if (isset(CSHJUNKIEQUOTES) && c == '\n') {
- X if (bptr[-1] == '\\') unadd(); else break;
- X }
- X add(c);
- X }
- X if (c != '\'') {
- X zerr("unmatched \'",NULL,0);
- X peek = LEXERR;
- X goto brk;
- X }
- X d = hgetc();
- X if (d != '\'' || unset(RCQUOTES)) break;
- X add(c);
- X }
- X hungetc(d);
- X c = Nularg;
- X break;
- X case LX2_DQUOTE:
- X add(Nularg);
- X while ((c = hgetc()) != '\"' && !lexstop)
- X if (c == '\\')
- X {
- X c = hgetc();
- X if (c != '\n')
- X {
- X if (c != '$' && c != '\\' && c != '\"' && c != '`')
- X add('\\');
- X add(c);
- X }
- X }
- X else {
- X if (isset(CSHJUNKIEQUOTES) && c == '\n') {
- X if (bptr[-1] == '\\') unadd(); else break;
- X }
- X if (c == '$') {
- X d = hgetc();
- X if (d == '(') {
- X add(Qstring);
- X if (skipcomm()) { peek = LEXERR; goto brk; }
- X c = Outpar;
- X } else if (d == '[') {
- X add(String);
- X add(Inbrack);
- X while ((c = hgetc()) != ']' && !lexstop)
- X add(c);
- X c = Outbrack;
- X } else {
- X c = Qstring;
- X hungetc(d);
- X }
- X } else if (c == '`')
- X c = Qtick;
- X add(c);
- X }
- X if (c != '\"') {
- X zerr("unmatched \"",NULL,0);
- X peek = LEXERR;
- X goto brk;
- X }
- X c = Nularg;
- X break;
- X case LX2_BQUOTE:
- X add(Tick);
- X parbegin = inbufct;
- X while ((c = hgetc()) != '`' && !lexstop)
- X if (c == '\\')
- X {
- X c = hgetc();
- X if (c != '\n')
- X {
- X if (c != '`' && c != '\\' && c != '$')
- X add('\\');
- X add(c);
- X }
- X }
- X else {
- X if (isset(CSHJUNKIEQUOTES) && c == '\n') {
- X if (bptr[-1] == '\\') unadd(); else break;
- X }
- X add(c);
- X }
- X if (c != '`') {
- X if (!zleparse) zerr("unmatched `",NULL,0);
- X peek = LEXERR;
- X goto brk;
- X }
- X c = Tick;
- X parbegin = -1;
- X break;
- X }
- X add(c);
- X c = hgetc();
- X if (intpos)
- X intpos--;
- X if (lexstop)
- X break;
- X }
- Xbrk:
- X hungetc(c);
- X *bptr = '\0';
- X return peek;
- X}
- X
- X/* expand aliases, perhaps */
- X
- Xint exalias() /**/
- X{
- Xstruct alias *an;
- Xchar *s,*t;
- X
- X s = yytext = hwadd();
- X for (t = s; *t && *t != HISTSPACE; t++);
- X if (!*t)
- X t = NULL;
- X else
- X *t = '\0';
- X if (interact && isset(SHINSTDIN) && !strin && !incasepat && tok == STRING &&
- X (isset(CORRECTALL) || (isset(CORRECT) && incmdpos)) && !nocorrect)
- X spckword(&tokstr,&s,&t,!incmdpos,1);
- X if (zleparse && !alstackind)
- X gotword(s);
- X an = gethnode(s,aliastab);
- X if (t)
- X *t = HISTSPACE;
- X if (alstackind != MAXAL && an && !an->inuse)
- X if (!(an->cmd && !incmdpos && alstat != ALSTAT_MORE))
- X {
- X if (an->cmd < 0)
- X {
- X tok = DO-an->cmd-1;
- X return 0;
- X }
- X else
- X {
- X an->inuse = 1;
- X hungets(ALPOPS);
- X hungets((alstack[alstackind++] = an)->text);
- X alstat = 0;
- X /* remove from history if it begins with space */
- X if (isset(HISTIGNORESPACE) && an->text[0] == ' ')
- X remhist();
- X lexstop = 0;
- X return 1;
- X }
- X }
- X return 0;
- X}
- X
- X/* skip (...) */
- X
- Xint skipcomm() /**/
- X{
- Xint pct = 1,c;
- X
- X parbegin = inbufct;
- X c = Inpar;
- X do
- X {
- X add(c);
- X c = hgetc();
- X if (itok(c) || lexstop)
- X break;
- X else if (c == '(') pct++;
- X else if (c == ')') pct--;
- X else if (c == '\\')
- X {
- X add(c);
- X c = hgetc();
- X }
- X else if (c == '\'')
- X {
- X add(c);
- X while ((c = hgetc()) != '\'' && !lexstop)
- X add(c);
- X }
- X else if (c == '\"')
- X {
- X add(c);
- X while ((c = hgetc()) != '\"' && !lexstop)
- X if (c == '\\')
- X {
- X add(c);
- X add(hgetc());
- X }
- X else add(c);
- X }
- X else if (c == '`')
- X {
- X add(c);
- X while ((c = hgetc()) != '`' && !lexstop)
- X if (c == '\\') add(c), add(hgetc());
- X else add(c);
- X }
- X }
- X while(pct);
- X if (!lexstop) parbegin = -1;
- X return lexstop;
- X}
- X
- SHAR_EOF
- chmod 0644 zsh2.1/src/lex.c ||
- echo 'restore of zsh2.1/src/lex.c failed'
- Wc_c="`wc -c < 'zsh2.1/src/lex.c'`"
- test 15750 -eq "$Wc_c" ||
- echo 'zsh2.1/src/lex.c: original size 15750, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= zsh2.1/src/loop.c ==============
- if test -f 'zsh2.1/src/loop.c' -a X"$1" != X"-c"; then
- echo 'x - skipping zsh2.1/src/loop.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting zsh2.1/src/loop.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/loop.c' &&
- X/*
- X
- X loop.c - loop execution
- X
- X This file is part of zsh, the Z shell.
- X
- X zsh is free software; no one can prevent you from reading the source
- X code, or giving it to someone else.
- X This file is copyrighted under the GNU General Public License, which
- X can be found in the file called COPYING.
- X
- X Copyright (C) 1990, 1991 Paul Falstad
- X
- X zsh is distributed in the hope that it will be useful, but
- X WITHOUT ANY WARRANTY. No author or distributor accepts
- X responsibility to anyone for the consequences of using it or for
- X whether it serves any particular purpose or works at all, unless he
- X says so in writing. Refer to the GNU General Public License
- X for full details.
- X
- X Everyone is granted permission to copy, modify and redistribute
- X zsh, but only under the conditions described in the GNU General Public
- X License. A copy of this license is supposed to have been given to you
- X along with zsh so you can know your rights and responsibilities.
- X It should be in a file named COPYING.
- X
- X Among other things, the copyright notice and this notice must be
- X preserved on all copies.
- X
- X*/
- X
- X#include "zsh.h"
- X
- Xint execfor(cmd) /**/
- XCmd cmd;
- X{
- XList list;
- Xstruct forcmd *node;
- Xchar *str;
- XLklist args;
- Xint cj = thisjob;
- X
- X loops++;
- X exiting = 0;
- X node = cmd->u.forcmd;
- X args = cmd->args;
- X if (!node->inflag)
- X {
- X char **x;
- X
- X args = newlist();
- X for (x = pparams; *x; x++)
- X addnode(args,ztrdup(*x));
- X }
- X pushheap();
- X while (str = ugetnode(args))
- X {
- X setsparam(node->name,ztrdup(str));
- X list = dupstruct(node->list);
- X execlist(list);
- X if (breaks)
- X {
- X breaks--;
- X if (breaks || !contflag)
- X break;
- X contflag = 0;
- X }
- X if (errflag)
- X {
- X lastval = 1;
- X break;
- X }
- X freeheap();
- X }
- X popheap();
- X thisjob = cj;
- X return lastval;
- X}
- X
- Xint execselect(cmd) /**/
- XCmd cmd;
- X{
- XList list;
- Xstruct forcmd *node;
- Xchar *str,*s;
- XLklist args;
- XLknode n;
- Xint cj = thisjob,t0;
- X
- X loops++;
- X node = cmd->u.forcmd;
- X args = cmd->args;
- X if (!full(args))
- X return 1;
- X exiting = 0;
- X pushheap();
- X for (;;)
- X {
- X do
- X {
- X selectlist(args);
- X if (interact && SHTTY != -1 && isset(USEZLE))
- X {
- X int pl;
- X
- X str = putprompt(prompt3,&pl);
- X str = zleread(str,NULL,pl);
- X }
- X else
- X str = fgets(zalloc(256),256,bshin);
- X if (!str || errflag)
- X {
- X fprintf(stderr,"\n");
- X fflush(stderr);
- X goto done;
- X }
- X if (s = strchr(str,'\n'))
- X *s = '\0';
- X }
- X while (!*str);
- X setsparam("REPLY",ztrdup(str));
- X t0 = atoi(str);
- X if (!t0)
- X str = "";
- X else
- X {
- X for (t0--,n = firstnode(args); n && t0; incnode(n),t0--);
- X if (n)
- X str = getdata(n);
- X else
- X str = "";
- X }
- X setsparam(node->name,ztrdup(str));
- X list = dupstruct(node->list);
- X execlist(list);
- X freeheap();
- X if (breaks)
- X {
- X breaks--;
- X if (breaks || !contflag)
- X break;
- X contflag = 0;
- X }
- X if (errflag)
- X break;
- X }
- Xdone:
- X popheap();
- X thisjob = cj;
- X return lastval;
- X}
- X
- Xint execwhile(cmd) /**/
- XCmd cmd;
- X{
- XList list;
- Xstruct whilecmd *node;
- Xint cj = thisjob;
- X
- X loops++;
- X node = cmd->u.whilecmd;
- X exiting = 0;
- X pushheap();
- X for(;;)
- X {
- X list = dupstruct(node->cont);
- X execlist(list);
- X if (!((lastval == 0) ^ node->cond))
- X break;
- X list = dupstruct(node->loop);
- X execlist(list);
- X if (breaks)
- X {
- X breaks--;
- X if (breaks || !contflag)
- X break;
- X contflag = 0;
- X }
- X freeheap();
- X if (errflag)
- X {
- X lastval = 1;
- X break;
- X }
- X }
- X popheap();
- X thisjob = cj;
- X return lastval;
- X}
- X
- Xint execrepeat(cmd) /**/
- XCmd cmd;
- X{
- XList list;
- Xint cj = thisjob,count;
- X
- X loops++;
- X exiting = 0;
- X if (!full(cmd->args) || nextnode(firstnode(cmd->args)))
- X {
- X zerr("bad argument for repeat",NULL,0);
- X return 1;
- X }
- X count = atoi(peekfirst(cmd->args));
- X pushheap();
- X while (count--)
- X {
- X list = dupstruct(cmd->u.list);
- X execlist(list);
- X freeheap();
- X if (breaks)
- X {
- X breaks--;
- X if (breaks || !contflag)
- X break;
- X contflag = 0;
- X }
- X if (lastval)
- X break;
- X if (errflag)
- X {
- X lastval = 1;
- X break;
- X }
- X }
- X popheap();
- X thisjob = cj;
- X return lastval;
- X}
- X
- Xint execif(cmd) /**/
- XCmd cmd;
- X{
- Xstruct ifcmd *node;
- Xint cj = thisjob;
- X
- X node = cmd->u.ifcmd;
- X exiting = 0;
- X while (node)
- X {
- X if (node->ifl)
- X {
- X execlist(node->ifl);
- X if (lastval)
- X {
- X node = node->next;
- X continue;
- X }
- X }
- X execlist(node->thenl);
- X break;
- X }
- X thisjob = cj;
- X return lastval;
- X}
- X
- Xint execcase(cmd) /**/
- XCmd cmd;
- X{
- Xstruct casecmd *node;
- Xchar *word;
- XLklist args;
- Xint cj = thisjob;
- X
- X node = cmd->u.casecmd;
- X args = cmd->args;
- X exiting = 0;
- X if (firstnode(args) && nextnode(firstnode(args)))
- X {
- X zerr("too many arguments to case",NULL,0);
- X errflag = 1;
- X return 1;
- X }
- X if (!full(args))
- X word = strdup("");
- X else
- X word = peekfirst(args);
- X while (node)
- X {
- X singsub(&(node->pat));
- X if (matchpat(word,node->pat))
- X break;
- X else
- X node = node->next;
- X }
- X if (node && node->list)
- X execlist(node->list);
- X thisjob = cj;
- X return lastval;
- X}
- SHAR_EOF
- chmod 0644 zsh2.1/src/loop.c ||
- echo 'restore of zsh2.1/src/loop.c failed'
- Wc_c="`wc -c < 'zsh2.1/src/loop.c'`"
- test 4854 -eq "$Wc_c" ||
- echo 'zsh2.1/src/loop.c: original size 4854, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= zsh2.1/src/math.c ==============
- if test -f 'zsh2.1/src/math.c' -a X"$1" != X"-c"; then
- echo 'x - skipping zsh2.1/src/math.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting zsh2.1/src/math.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/math.c' &&
- X/*
- X
- X math.c - mathematical expression evaluation
- X
- X This file is part of zsh, the Z shell.
- X
- X zsh is free software; no one can prevent you from reading the source
- X code, or giving it to someone else.
- X
- X This file is copyrighted under the GNU General Public License, which
- X can be found in the file called COPYING.
- X
- X Copyright (C) 1990, 1991 Paul Falstad
- X
- X zsh is distributed in the hope that it will be useful, but
- X WITHOUT ANY WARRANTY. No author or distributor accepts
- X responsibility to anyone for the consequences of using it or for
- X whether it serves any particular purpose or works at all, unless he
- X says so in writing. Refer to the GNU General Public License
- X for full details.
- X
- X Everyone is granted permission to copy, modify and redistribute
- X zsh, but only under the conditions described in the GNU General Public
- X License. A copy of this license is supposed to have been given to you
- X along with zsh so you can know your rights and responsibilities.
- X It should be in a file named COPYING.
- X
- X Among other things, the copyright notice and this notice must be
- X preserved on all copies.
- X
- X*/
- X
- X#include "zsh.h"
- X
- Xstatic char *ptr;
- X
- Xtypedef int LV;
- X
- Xstatic long yyval;
- Xstatic LV yylval;
- X
- X/* nonzero means we are not evaluating, just parsing */
- X
- Xstatic int noeval = 0;
- X
- X/* != 0 means recognize unary plus, minus, etc. */
- X
- Xstatic int unary = 1;
- X
- Xvoid mathparse DCLPROTO((int));
- X
- X/* LR = left-to-right associativity
- X RL = right-to-left associativity
- X BOO = short-circuiting boolean */
- X
- X#define LR 0
- X#define RL 1
- X#define BOOL 2
- X
- X#define M_INPAR 0
- X#define M_OUTPAR 1
- X#define NOT 2
- X#define COMP 3
- X#define POSTPLUS 4
- X#define POSTMINUS 5
- X#define UPLUS 6
- X#define UMINUS 7
- X#define AND 8
- X#define XOR 9
- X#define OR 10
- X#define MUL 11
- X#define DIV 12
- X#define MOD 13
- X#define PLUS 14
- X#define MINUS 15
- X#define SHLEFT 16
- X#define SHRIGHT 17
- X#define LES 18
- X#define LEQ 19
- X#define GRE 20
- X#define GEQ 21
- X#define DEQ 22
- X#define NEQ 23
- X#define DAND 24
- X#define DOR 25
- X#define DXOR 26
- X#define QUEST 27
- X#define COLON 28
- X#define EQ 29
- X#define PLUSEQ 30
- X#define MINUSEQ 31
- X#define MULEQ 32
- X#define DIVEQ 33
- X#define MODEQ 34
- X#define ANDEQ 35
- X#define XOREQ 36
- X#define OREQ 37
- X#define SHLEFTEQ 38
- X#define SHRIGHTEQ 39
- X#define DANDEQ 40
- X#define DOREQ 41
- X#define DXOREQ 42
- X#define COMMA 43
- X#define EOI 44
- X#define PREPLUS 45
- X#define PREMINUS 46
- X#define NUM 47
- X#define ID 48
- X#define TOKCOUNT 49
- X
- X/* precedences */
- X
- Xstatic int prec[TOKCOUNT] = {
- X 1,137,2,2,2,
- X 2,2,2,4,5,
- X 6,7,7,7,8,
- X 8,3,3,9,9,
- X 9,9,10,10,11,
- X 12,12,13,13,14,
- X 14,14,14,14,14,
- X 14,14,14,14,14,
- X 14,14,14,15,200,
- X 2,2,0,0,
- X};
- X
- X#define TOPPREC 15
- X#define ARGPREC (15-1)
- X
- Xstatic int type[TOKCOUNT] = {
- X LR,LR,RL,RL,RL,
- X RL,RL,RL,LR,LR,
- X LR,LR,LR,LR,LR,
- X LR,LR,LR,LR,LR,
- X LR,LR,LR,LR,BOOL,
- X BOOL,LR,RL,RL,RL,
- X RL,RL,RL,RL,RL,
- X RL,RL,RL,RL,RL,
- X BOOL,BOOL,RL,RL,RL,
- X RL,RL,LR,LR,
- X};
- X
- X#define LVCOUNT 32
- X
- X/* list of lvalues (variables) */
- X
- Xstatic int lvc;
- Xstatic char *lvals[LVCOUNT];
- X
- Xint zzlex() /**/
- X{
- X for(;;)
- X switch (*ptr++)
- X {
- X case '+':
- X if (*ptr == '+' && (unary || !ialnum(*ptr)))
- X {
- X ptr++;
- X return (unary) ? PREPLUS : POSTPLUS;
- X }
- X if (*ptr == '=') { unary = 1; ptr++; return PLUSEQ; }
- X return (unary) ? UPLUS : PLUS;
- X case '-':
- X if (*ptr == '-' && (unary || !ialnum(*ptr)))
- X {
- X ptr++;
- X return (unary) ? PREMINUS : POSTMINUS;
- X }
- X if (*ptr == '=') { unary = 1; ptr++; return MINUSEQ; }
- X return (unary) ? UMINUS : MINUS;
- X case '(': unary = 1; return M_INPAR;
- X case ')': return M_OUTPAR;
- X case '!': if (*ptr == '=')
- X { unary = 1; ptr++; return NEQ; }
- X return NOT;
- X case '~': return COMP;
- X case '&': unary = 1;
- X if (*ptr == '&') { if (*++ptr == '=')
- X { ptr++; return DANDEQ; } return DAND; }
- X else if (*ptr == '=') { ptr++; return ANDEQ; } return AND;
- X case '|': unary = 1;
- X if (*ptr == '|') { if (*++ptr == '=')
- X { ptr++; return DOREQ; } return DOR; }
- X else if (*ptr == '=') { ptr++; return OREQ; } return OR;
- X case '^': unary = 1;
- X if (*ptr == '^') { if (*++ptr == '=')
- X { ptr++; return DXOREQ; } return DXOR; }
- X else if (*ptr == '=') { ptr++; return XOREQ; } return XOR;
- X case '*': unary = 1;
- X if (*ptr == '=') { ptr++; return MULEQ; } return MUL;
- X case '/': unary = 1;
- X if (*ptr == '=') { ptr++; return DIVEQ; } return DIV;
- X case '%': unary = 1;
- X if (*ptr == '=') { ptr++; return MODEQ; } return MOD;
- X case '<': unary = 1; if (*ptr == '<')
- X { if (*++ptr == '=') { ptr++; return SHLEFTEQ; } return SHLEFT; }
- X else if (*ptr == '=') { ptr++; return LEQ; } return LES;
- X case '>': unary = 1; if (*ptr == '>')
- X { if (*++ptr == '=') { ptr++; return SHRIGHTEQ; } return SHRIGHT; }
- X else if (*ptr == '=') { ptr++; return GEQ; } return GRE;
- X case '=': unary = 1; if (*ptr == '=') { ptr++; return DEQ; }
- X return EQ;
- X case '?': unary = 1; return QUEST;
- X case ':': unary = 1; return COLON;
- X case ',': unary = 1; return COMMA;
- X case '\0': unary = 1; ptr--; return EOI;
- X case '[': unary = 0;
- X { int base = zstrtol(ptr,&ptr,10);
- X if (*ptr == ']') ptr++;
- X yyval = zstrtol(ptr,&ptr,lastbase = base);
- X return NUM; }
- X case ' ': case '\t':
- X break;
- X default:
- X if (idigit(*--ptr))
- X { unary = 0; yyval = zstrtol(ptr,&ptr,10); return NUM; }
- X if (ialpha(*ptr) || *ptr == '$')
- X {
- X char *p,q;
- X
- X if (*ptr == '$')
- X ptr++;
- X p = ptr;
- X if (lvc == LVCOUNT)
- X {
- X zerr("too many identifiers (complain to author)",NULL,0);
- X return EOI;
- X }
- X unary = 0;
- X while(ialpha(*++ptr));
- X q = *ptr;
- X *ptr = '\0';
- X lvals[yylval = lvc++] = ztrdup(p);
- X *ptr = q;
- X return ID;
- X }
- X return EOI;
- X }
- X}
- X
- X/* the value stack */
- X
- X#define STACKSZ 100
- Xint mtok; /* last token */
- Xint sp = -1; /* stack pointer */
- Xstruct mathvalue {
- X LV lval;
- X long val;
- X } stack[STACKSZ];
- X
- Xvoid push(val,lval)
- Xlong val;LV lval;
- X{
- X if (sp == STACKSZ-1)
- X zerr("stack overflow",NULL,0);
- X else
- X sp++;
- X stack[sp].val = val;
- X stack[sp].lval = lval;
- X}
- X
- Xlong getvar(s)
- XLV s;
- X{
- Xlong t;
- X
- X if (!(t = getiparam(lvals[s])))
- X return 0;
- X return t;
- X}
- X
- Xlong setvar(s,v)
- XLV s;long v;
- X{
- X if (s == -1 || s >= lvc)
- X {
- X zerr("lvalue required",NULL,0);
- X return 0;
- X }
- X if (noeval)
- X return v;
- X setiparam(lvals[s],v);
- X return v;
- X}
- X
- Xint notzero(a) /**/
- Xint a;
- X{
- X if (a == 0)
- X {
- X zerr("division by zero",NULL,0);
- X return 0;
- X }
- X return 1;
- X}
- X
- X#define pop2() { b = stack[sp--].val; a = stack[sp--].val; }
- X#define pop3() {c=stack[sp--].val;b=stack[sp--].val;a=stack[sp--].val;}
- X#define nolval() {stack[sp].lval= -1;}
- X#define pushv(X) { push(X,-1); }
- X#define pop2lv() { pop2() lv = stack[sp+1].lval; }
- X#define set(X) { push(setvar(lv,X),lv); }
- X
- Xvoid op(what) /**/
- Xint what;
- X{
- Xlong a,b,c;
- XLV lv;
- X
- X if (sp < 0)
- X {
- X zerr("bad math expression: stack empty",NULL,0);
- X return;
- X }
- X switch(what) {
- X case NOT: stack[sp].val = !stack[sp].val; nolval(); break;
- X case COMP: stack[sp].val = ~stack[sp].val; nolval(); break;
- X case POSTPLUS: ( void ) setvar(stack[sp].lval,stack[sp].val+1); break;
- X case POSTMINUS: ( void ) setvar(stack[sp].lval,stack[sp].val-1); break;
- X case UPLUS: nolval(); break;
- X case UMINUS: stack[sp].val = -stack[sp].val; nolval(); break;
- X case AND: pop2(); pushv(a&b); break;
- X case XOR: pop2(); pushv(a^b); break;
- X case OR: pop2(); pushv(a|b); break;
- X case MUL: pop2(); pushv(a*b); break;
- X case DIV: pop2(); if (notzero(b)) pushv(a/b); break;
- X case MOD: pop2(); if (notzero(b)) pushv(a%b); break;
- X case PLUS: pop2(); pushv(a+b); break;
- X case MINUS: pop2(); pushv(a-b); break;
- X case SHLEFT: pop2(); pushv(a<<b); break;
- X case SHRIGHT: pop2(); pushv(a>>b); break;
- X case LES: pop2(); pushv(a<b); break;
- X case LEQ: pop2(); pushv(a<=b); break;
- X case GRE: pop2(); pushv(a>b); break;
- X case GEQ: pop2(); pushv(a>=b); break;
- X case DEQ: pop2(); pushv(a==b); break;
- X case NEQ: pop2(); pushv(a!=b); break;
- X case DAND: pop2(); pushv(a&&b); break;
- X case DOR: pop2(); pushv(a||b); break;
- X case DXOR: pop2(); pushv(a&&!b||!a&&b); break;
- X case QUEST: pop3(); pushv((a)?b:c); break;
- X case COLON: break;
- X case EQ: pop2lv(); set(b); break;
- X case PLUSEQ: pop2lv(); set(a+b); break;
- X case MINUSEQ: pop2lv(); set(a-b); break;
- X case MULEQ: pop2lv(); set(a*b); break;
- X case DIVEQ: pop2lv(); if (notzero(b)) set(a/b); break;
- X case MODEQ: pop2lv(); if (notzero(b)) set(a%b); break;
- X case ANDEQ: pop2lv(); set(a&b); break;
- X case XOREQ: pop2lv(); set(a^b); break;
- X case OREQ: pop2lv(); set(a|b); break;
- X case SHLEFTEQ: pop2lv(); set(a<<b); break;
- X case SHRIGHTEQ: pop2lv(); set(a>>b); break;
- X case DANDEQ: pop2lv(); set(a&&b); break;
- X case DOREQ: pop2lv(); set(a||b); break;
- X case DXOREQ: pop2lv(); set(a&&!b||!a&&b); break;
- X case COMMA: pop2(); pushv(b); break;
- X case PREPLUS: stack[sp].val = setvar(stack[sp].lval,
- X stack[sp].val+1); break;
- SHAR_EOF
- true || echo 'restore of zsh2.1/src/math.c failed'
- fi
- echo 'End of zsh2.1.0 part 8'
- echo 'File zsh2.1/src/math.c is continued in part 9'
- echo 9 > _shar_seq_.tmp
- exit 0
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-